package com.dcits.components;

import com.dcits.annotation.FieldCheck;
import com.dcits.annotation.ParamCheck;
import com.dcits.annotation.ValidateUtil;
import com.dcits.exception.ErrorCode;
import com.dcits.exception.ParamException;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.Objects;

@Slf4j
@Order(Integer.MIN_VALUE)
@Aspect
@Component
public class ParamCheckAspect {
    private static final String LOG_PREFIX = "[WebFilterAop] ";
    @Value("${http.request.print.enable:false}")
    private boolean httpRequestPrintEnable;

    // 拦截所有带 @ParamCheck 的方法
    @Around("@annotation(com.dcits.annotation.ParamCheck)")
    public Object validateParams(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        ParamCheck paramCheck = signature.getMethod().getAnnotation(ParamCheck.class);


        if (!Objects.isNull(paramCheck) && !paramCheck.enable()) {
            return joinPoint.proceed(); // 跳过校验
        }

        if (httpRequestPrintEnable) {
            log.info(LOG_PREFIX + "请求参数: {}", "目前为空，等待开发");
        }

        Object[] args = joinPoint.getArgs();
        for (Object arg : args) {
            if (arg != null) {
                checkFields(arg); // 递归校验对象属性
            }
        }
        return joinPoint.proceed(); // 校验通过，执行原方法
    }

    private void checkFields(Object obj) throws IllegalAccessException {
        for (Field field : obj.getClass().getDeclaredFields()) {
            field.setAccessible(true);
            FieldCheck annotation = field.getAnnotation(FieldCheck.class);
            if (annotation == null) continue;

            Object value = field.get(obj);
            // 执行校验规则（见下文工具类）
            final String errorMsg = ValidateUtil.checkField(field, value, annotation);
            if (errorMsg != null) {
                throw new ParamException(new ErrorCode("012000"), errorMsg);
            }
        }
    }
}
